﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine.UI;

namespace Nirvana
{
    /// <summary>
    /// 检查哪些资源的配置选项开启/关闭了，用于优化检查
    /// </summary>
    [CreateAssetMenu(fileName = "@AssetCheckRule", menuName = "Nirvana/Asset/AssetCheckRule")]
    public sealed class AssetCheckRule : ScriptableObject
    {
        [SerializeField]
        [Tooltip("The regex for include assets.")]
        private ListStringVariate includeRegexs;

        [SerializeField]
        [Tooltip("The regex for exclude assets.")]
        private ListStringVariate excludeRegexs;

        [Tooltip("How the check each model.")]
        [SerializeField]
        private CheckModel checkModel;

        [SerializeField]
        [Tooltip("How the check each animation.")]
        private CheckAnimation checkAnimation;

        [SerializeField]
        [Tooltip("How the check each texture.")]
        private CheckTexture checkTexture;

        [Tooltip("How the check each material.")]
        [SerializeField]
        private CheckMaterial checkMaterial;

        [Tooltip("How the check each material with Standrad Shader.")]
        [SerializeField]
        private CheckStanderdMaterial checkStanderdMaterial;

        [SerializeField]
        [Tooltip("How the check each audio.")]
        private CheckAudio checkAudio;

        [Tooltip("How the check each renderer.")]
        [SerializeField]
        private CheckRenderer checkRenderer;

        [SerializeField]
        [Tooltip("How the check each particle system.")]
        private CheckParticleSystem checkParticleSystem;

        // Token: 0x0400012E RID: 302
        [SerializeField]
        [Tooltip("How the check UI.")]
        private CheckUI checkUI;


        [Tooltip("The asset check report.")]
        [SerializeField]
        [HideInInspector]
        private AssetCheckReport report;

        public AssetCheckReport Report { get { return report; } }

        public static AssetCheckRule[] GetAllAssetCheckRule()
        {
            string[] array = AssetDatabase.FindAssets("t:AssetCheckRule");
            AssetCheckRule[] array2 = new AssetCheckRule[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                string text = array[i];
                string text2 = AssetDatabase.GUIDToAssetPath(text);
                array2[i] = AssetDatabase.LoadAssetAtPath<AssetCheckRule>(text2);
            }
            return array2;
        }

        public string GetDirectorName()
        {
            string assetpath = AssetDatabase.GetAssetPath(this);
            return Path.GetDirectoryName(assetpath);
        }

        public int GetTotalCount()
        {
            string assetpath = AssetDatabase.GetAssetPath(this);
            string dirname = Path.GetDirectoryName(assetpath);
            var allasset = AssetDatabase.FindAssets("", new string[] { dirname});
            allasset = allasset.RemoveDuplicate<string>();
            return allasset.Length;
        }

        public bool Progress(ProgressIndicator progress)
        {
            if (this.report == null) this.report = new AssetCheckReport();
            else this.report.Clear();

            if (!includeRegexs.IsHasValue()) return false;

            this.checkMaterial.Clear();

            Regex[] inRegexs = null;
            if (includeRegexs.IsHasValue())
            {
                var temparray = this.includeRegexs.GetValue().ToArray();
                if (temparray != null && temparray.Length > 0)
                {
                    inRegexs = new Regex[temparray.Length];
                    for (int i = 0; i < temparray.Length; i++) inRegexs[i] = new Regex(temparray[i]);
                }
            }

            Regex[] exRegexs = null;
            if (excludeRegexs.IsHasValue())
            {
                var temparray = this.excludeRegexs.GetValue().ToArray();
                if (temparray != null && temparray.Length > 0)
                {
                    exRegexs = new Regex[temparray.Length];
                    for (int i = 0; i < temparray.Length; i++) exRegexs[i] = new Regex(temparray[i]);
                }
            }

            string dirname = this.GetDirectorName();
            dirname = dirname.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            string[] allguids = AssetDatabase.FindAssets(string.Empty, new string[]
            {
                dirname
            });
            allguids = allguids.RemoveDuplicate<string>();

            foreach(var p in allguids)
            {
                string assetpath = AssetDatabase.GUIDToAssetPath(p);
                if (progress.Show("Check {0}", assetpath)) return true;

                progress.AddProgress(1f);
                if (!AssetDatabase.IsValidFolder(assetpath))
                {
                    string input = DirectoryUtil.RelativePath(dirname, assetpath);
                    if (inRegexs != null)
                    {
                        bool flag = false;
                        foreach (Regex r in inRegexs)
                        {
                            if (r.IsMatch(input))
                            {
                                flag = true;
                            }
                        }
                        if (!flag)
                        {
                            return false;
                        }
                    }
                    if (exRegexs != null)
                    {
                        bool flag2 = false;
                        foreach (Regex r in exRegexs)
                        {
                            if (r.IsMatch(input))
                            {
                                flag2 = true;
                                break;
                            }
                        }
                        if (flag2)
                        {
                            return false;
                        }
                    }
                    //todo
                    CheckRule(this.report, assetpath);
                }
            }
            return false;
        }

        private void CheckRule(AssetCheckReport report,string assetpath)
        {
            if (assetpath.EndsWith(".unity"))
            {
                return;
            }

            var allAssets = AssetDatabase.LoadAllAssetsAtPath(assetpath);
            if(allAssets.Length == 0)
            {
                Debug.Log("<color=yellow>The path: " + assetpath + " can not load.</color>");
                return;
            }

            if (allAssets[0] == null) return;

            report.assetpath = assetpath;
            report.objectname = allAssets[0].name;
            report.hierarchyPath = null;

            var import = AssetImporter.GetAtPath(assetpath);
            if(import as AudioImporter != null)
            {
                this.checkAudio.CheckAudioImporter(report, import as AudioImporter);
            }

            if (import as ModelImporter != null)
            {
                this.checkModel.FilterModel(report, import as ModelImporter);
            }

            if (import as TextureImporter != null)
            {
                this.checkTexture.CheckTextureImporter(report, import as TextureImporter);
            }

            bool isPrefab = assetpath.EndsWith(".prefab");
            foreach(var obj in allAssets)
            {
                if(obj != null)
                {
                    report.objectname = obj.name;
                    report.hierarchyPath = "";
                    if (obj as Texture != null)
                    {
                        this.checkTexture.CheckTextureMaxSize(report, obj as Texture);
                        continue;
                    }
                    if (obj as Material != null)
                    {
                        this.checkMaterial.CheckMaterials(report, obj as Material);
                        this.checkStanderdMaterial.CheckMaterials(report, obj as Material);
                        continue;
                    }
                    if (obj as Mesh != null)
                    {
                        this.checkModel.FilterMesh(report, obj as Mesh);
                        continue;
                    }
                    if (obj as AnimationClip != null)
                    {
                        this.checkAnimation.CheckAnimationClip(report, obj as AnimationClip);
                        continue;
                    }
                    if (obj as SkinnedMeshRenderer != null)
                    {
                        this.checkAnimation.CheckSkinMesh(report, obj as SkinnedMeshRenderer);
                        continue;
                    }
                    if (obj as AudioClip != null)
                    {
                        this.checkAudio.CheckAudioClip(report, obj as AudioClip);
                        continue;
                    }

                    if (obj as Renderer != null)
                    {
                        this.checkRenderer.CheckRender(report, obj as Renderer);
                        continue;
                    }

                    if (obj as ParticleSystem != null)
                    {
                        this.checkParticleSystem.CheckParitcle(report, obj as ParticleSystem);
                        continue;
                    }

                    if (obj as RectTransform != null)
                    {
                        this.checkUI.checkPosZtoZero(report, obj as RectTransform);
                        continue;
                    }


                    if (obj as Canvas != null)
                    {
                        this.checkUI.CheckCanvas(report, obj as Canvas);
                        continue;
                    }

                    if (obj as CanvasScaler != null)
                    {
                        this.checkUI.CheckCanvasScaler(report, obj as CanvasScaler);
                        continue;
                    }

                    if (obj as CanvasRenderer != null)
                    {
                        this.checkUI.CheckEmptyCanvasRenderer(report, obj as CanvasRenderer);
                        continue;
                    }

                    if (obj as MaskableGraphic != null)
                    {
                        this.checkUI.CheckMaskableGraphic(report, obj as MaskableGraphic);
                        continue;
                    }

                    if (obj as Text != null)
                    {
                        this.checkUI.CheckText(report, obj as Text);
                        continue;
                    }

                    if (obj as ScrollRect != null)
                    {
                        this.checkUI.CheckScrollRect(report, obj as ScrollRect);
                        continue;
                    }

                    if (obj as UIVariableTable != null)
                    {
                        this.checkUI.CheckUIVariableTable(report, obj as UIVariableTable);
                        continue;
                    }

                }
            }




        }



    }
}

